using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;

using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Mathematics;


namespace BriansClimb.Climber
{
    /// <summary>
    /// This is the BodyPart class that makes up both the climber's body parts and
    /// the holds during the PlayerClimbScene.  It is a DrawableGameObject
    /// </summary>
    /// 
 
    public class BodyPart : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private Texture2D texture;
        private Body body;
        private Microsoft.Xna.Framework.Vector2 origin;
        private FarseerGames.FarseerPhysics.Mathematics.Vector2 position;
        //!Geometry object of the body part
        private Geom geom;
        private PhysicsSimulator physicsSimulator;
        private Game game;
        //!Name of the body part
        private string name;
        //!Friction of the body part
        protected int friction=4;
        private int height, weight, width;
        private Rectangle textureRectangle;
        //!If the body part is selected
        protected bool selected=false;
        //!If the body part is holding a hold
        protected bool isHolding = false;

        public BodyPart(Game game)
            : base(game)
        {
            textureRectangle = new Rectangle();
            // TODO: Construct any child components here
        }
        /// <summary>
        /// Constructs a named rectangular body part based on the passed parameters.
        /// </summary>
        /// <param name="width">Width of the body part.</param>
        /// <param name="height">Height of the body part.</param>
        /// <param name="weight">Weight of the body part.</param>
        /// <param name="tex">Texture of the body part.</param>
        /// <param name="physicsSimulator">PhysicsSimulator to add the body part to.</param>
        /// <param name="positionIn">Initial position of the body part</param>
        /// <returns>PhysicsSimulator</returns>
        public PhysicsSimulator makeBodyPart(int width, int height, int weight, Texture2D tex, PhysicsSimulator physicsSimulator, FarseerGames.FarseerPhysics.Mathematics.Vector2 positionIn, string name)
        {
            //Setting all initial values based on passed in parameters
            this.height = height;
            this.weight = weight;
            this.width = width;
            texture = tex;
            this.name = name;
            this.physicsSimulator = physicsSimulator;
            body = BodyFactory.Instance.CreateRectangleBody(physicsSimulator, width,height,weight);
            textureRectangle = new Rectangle((int)positionIn.X, (int)positionIn.Y, this.width, this.height);
            position = positionIn;
            body.Position = positionIn;
            geom = GeomFactory.Instance.CreateRectangleGeom(physicsSimulator, body, width,height);
            //Adds the geometry object to the physics simulator
            physicsSimulator.Add(geom);
            //Sets the origin of the body part to the center of the given texture
            origin = new Microsoft.Xna.Framework.Vector2(texture.Width / 2f, texture.Height / 2f);
            return physicsSimulator;            
        }
        /// <summary>
        /// Constructs a circle body part based on the passed parameters.
        /// </summary>
        /// <param name="width">The</param>
        /// <param name="height"></param>
        /// <param name="weight"></param>
        /// <param name="tex"></param>
        /// <param name="physicsSimulator"></param>
        /// <param name="positionIn"></param>
        /// <param name="name"></param>
        /// <param name="circle"></param>
        /// <returns></returns>
        public PhysicsSimulator makeBodyPart(int width, int height, int weight, Texture2D tex, PhysicsSimulator physicsSimulator, FarseerGames.FarseerPhysics.Mathematics.Vector2 positionIn, string name, int circle)
        {
            this.height = height;
            this.weight = weight;
            this.width = width;
            this.name = name;
            texture = tex;
            this.physicsSimulator = physicsSimulator;
            body = BodyFactory.Instance.CreateRectangleBody(physicsSimulator, width, height, weight);
            textureRectangle = new Rectangle((int)positionIn.X, (int)positionIn.Y, this.width, this.height);
            position = positionIn;
            body.Position = positionIn;
            geom = GeomFactory.Instance.CreateCircleGeom(physicsSimulator, body, this.width / 2, 10);
            Console.WriteLine(textureRectangle.Width);
            //geom = GeomFactory.Instance.CreateRectangleGeom(physicsSimulator, body, width, height);
            physicsSimulator.Add(geom);
            origin = new Microsoft.Xna.Framework.Vector2(texture.Width / 2f, texture.Height / 2f);
            return physicsSimulator;
        }
        /// <summary>
        /// Creates an unnamed, untextured body part.
        /// </summary>
        /// <param name="width">Width of the body part</param>
        /// <param name="height">Height of the body part</param>
        /// <param name="physicsSimulator">Physics Simulator to add the body part to</param>
        /// <param name="positionIn">Initial position of the body part</param>
        /// <returns></returns>
        public PhysicsSimulator makeBodyPart(int width, int height, PhysicsSimulator physicsSimulator, FarseerGames.FarseerPhysics.Mathematics.Vector2 positionIn)
        {
            this.height = height;
            this.weight = 1;
            this.width = width;
             this.physicsSimulator = physicsSimulator;
            body = BodyFactory.Instance.CreateRectangleBody(physicsSimulator, width, height, 1);
            position = positionIn;
            body.Position = positionIn;
            textureRectangle = new Rectangle((int)positionIn.X, (int)positionIn.Y, width, height);
            geom = GeomFactory.Instance.CreateRectangleGeom(physicsSimulator, body, width, height);
            physicsSimulator.Add(geom);
            this.setIsHold(true);            
            return physicsSimulator;
        }
        
        /// <summary>
        /// Returns the Body object of the BodyPart.
        /// </summary>
        /// <returns>Body object.</returns>
        public Body getBody()
        {
            return body;
        }
        /// <summary>
        /// Sets the Body object for the BodyPart.
        /// </summary>
        /// <param name="bodyIn">The body to set.</param>
        public void setBody(Body bodyIn)
        {
            body = bodyIn;
        }
        /// <summary>
        /// This attribute represents the friction of the body part.
        /// </summary>
        public int HandFriction
        {
            get { return friction; }
            set { friction = value; }
        }

        /// <summary>
        /// This attribute represents of the body part is selected or not.
        /// </summary>
        public bool IsSelected
        {
            get { return selected; }
            set { selected = value; }
        }

        /// <summary>
        /// This attribute indicates if the body part is holding a hold.
        /// </summary>
        public bool IsHolding
        {
            get { return isHolding; }
            set { isHolding = value; }
        }

        /// <summary>
        /// Returns the origin of the body part.
        /// </summary>
        /// <returns>Origin of the body part.</returns>
        public Microsoft.Xna.Framework.Vector2 getOrigin()
        {
            return origin;
        }

        /// <summary>
        /// Sets the origin of the body part.
        /// </summary>
        /// <param name="originIn">The origin that the body part will have</param>
        public void setOrigin(Microsoft.Xna.Framework.Vector2 originIn)
        {
            origin = originIn;
        }

        /// <summary>
        /// Returns the geometry object of the body part.
        /// </summary>
        /// <returns>Geometry object of the body part.</returns>
        public Geom getGeom()
        {
            return geom;
        }

        /// <summary>
        /// Sets the geometry object of the body part.
        /// </summary>
        /// <param name="geomIn">The geometry object the body part will have</param>
        public void setGeom(Geom geomIn)
        {
            geom = geomIn;
        }

        /// <summary>
        /// Sets the texture of the body part.
        /// </summary>
        /// <param name="texIn">The texture the body part will have</param>
        public void setTexture(Texture2D texIn)
        {
            texture = texIn;
        }

        /// <summary>
        /// Returns the texture of the body part.
        /// </summary>
        /// <returns>The body part's texture</returns>
        public Texture2D getTexture()
        {
            return texture;
        }

        /// <summary>
        /// Returns the name of the body part.
        /// </summary>
        /// <returns>The name of the body part</returns>
        public string getName()
        {
            return name;
        }

        /// <summary>
        /// Sets the position of the body part.
        /// </summary>
        /// <param name="positionIn">The position to set the body part to</param>
        public void setPosition(FarseerGames.FarseerPhysics.Mathematics.Vector2 positionIn)
        {
            position = positionIn;
        }

        /// <summary>
        /// Returns the position of the body part.
        /// </summary>
        /// <returns>The position of the body part</returns>
        public FarseerGames.FarseerPhysics.Mathematics.Vector2 getPosition()
        {
            return position;
        }

        /// <summary>
        /// Returns the entire Body Part object.
        /// </summary>
        /// <returns>This body part</returns>
        public BodyPart getBodyPart()
        {
            return this;
        }

        /// <summary>
        /// Sets the body part to be static.
        /// </summary>
        /// <param name="boolIn">Bool value to set it to.</param>
        public void setIsStatic(bool boolIn)
        {
            body.isStatic = true;
        }

        /// <summary>
        /// Used to designate if the body part is a hand.
        /// </summary>
        /// <param name="boolIn">THe bool value to set isHand to.</param>
        public void setIsHand(bool boolIn)
        {
            if (boolIn == true)
                body.isHand = true;
            else if (boolIn == false)
                body.isHand = false;
        }

        /// <summary>
        /// Used to designate if the body part is a hold.
        /// </summary>
        /// <param name="boolIn">The bool value to set isHold to.</param>
        public void setIsHold(bool boolIn)
        {
            if (boolIn == true)
            {
                body.isHold = true;
                body.isStatic = true;
                
            }
            else if (boolIn == false)
                body.isHold = false;
        }

        /// <summary>
        /// Returns the rectangular texture.  Depricated
        /// </summary>
        /// <returns>The texture rectangle.</returns>
        public Rectangle getTextureRectangle()
        {
            return textureRectangle;
        }

        /// <summary>
        /// Sets the texture rectangle
        /// </summary>
        /// <param name="textureRectIn">The texture rectangle to set.</param>
        public void setTextureRectangle(Rectangle textureRectIn)
        {
            textureRectangle = textureRectIn;
        }

        /// <summary>
        /// Indicates to the climber to remove herself.
        /// </summary>
        public void removeSelf()
        {
            if (this.geom != null)
            {
                
                this.geom.Dispose();
                
            }
            if (this.body != null)
            {
                
                this.body.Dispose();
                
            }
            
        }

        /// <summary>
        /// The attribute of the Body object of the BodyPart
        /// </summary>
        public Body Body
        {
            get { return body; }
            set { body = value; }
        }

        /// <summary>
        /// The attribute of the Geometry object of the BodyPart
        /// </summary>
        public Geom Geom
        {
            get { return geom; }
            set { geom = value; }
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here

            base.Update(gameTime);
        }
        /// <summary>
        /// Allows the game component to draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Draw(GameTime gameTime)
        {
            
            base.Draw(gameTime);
        }
    }
}